package ms.jasim.console.gui.component;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;

import ms.jasim.framework.PddlModel;
import ms.spm.IAppContext;

public class ME_GoalPanel extends JContextualPanel {

	public static final ImageIcon ICON_ADD_GOAL = new ImageIcon("resources/goal_add_16x16.png");
	public static final ImageIcon ICON_REMOVE_GOAL = new ImageIcon("resources/goal_remove_16x16.png");
	
	private static final long serialVersionUID = 1L;
	private GoalTableModel goalModel;
	private PddlModel model;

	public ME_GoalPanel() {
		setLayout(new BorderLayout());

		IntegerEditor defaultIntEditor = new IntegerEditor(0, Integer.MAX_VALUE);

		// create the role table
		final JTable goalTable = new JTable(goalModel = new GoalTableModel());
		goalTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "selectNextColumnCell");
		goalTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		goalTable.setDefaultEditor(int.class, defaultIntEditor);

		setColumnInfo(goalTable, GoalTableModel.COL_NAME, 150, 50, Integer.MAX_VALUE, null);
		setColumnInfo(goalTable, GoalTableModel.COL_TEXT, 300, 50, Integer.MAX_VALUE, null);
		setColumnInfo(goalTable, GoalTableModel.COL_MAX_SATISFACTION, 90, 90, Integer.MAX_VALUE, defaultIntEditor);
		setColumnInfo(goalTable, GoalTableModel.COL_CRITICALITY, 90, 90, Integer.MAX_VALUE, defaultIntEditor);

		// create role command: add/remove
		JPanel roleTableCommand = new JPanel(new FlowLayout(FlowLayout.LEFT));
		JButton cmdAddRole = new JButton("Add goal", ICON_ADD_GOAL);
		cmdAddRole.setMnemonic('A');
		cmdAddRole.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				goalModel.createNewGoal();
				goalTable.requestFocusInWindow();
				goalTable.changeSelection(goalModel.getRowCount() - 1, RoleTableModel.COL_NAME,  false, false);
			}

		});
		roleTableCommand.add(cmdAddRole);

		JButton cmdRemoveRole = new JButton("Remove goals", ICON_REMOVE_GOAL);
		cmdRemoveRole.setMnemonic('R');
		cmdRemoveRole.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				ListSelectionModel selectionModel = goalTable.getSelectionModel();
				goalModel.deleteRoles(selectionModel.getMinSelectionIndex(), selectionModel.getMaxSelectionIndex());
			}

		});
		roleTableCommand.add(cmdRemoveRole);

		// create the goal panel
		JPanel roleTablePanel = new JPanel(new BorderLayout());
		roleTablePanel.add(new JScrollPane(goalTable), BorderLayout.CENTER);
		roleTablePanel.add(roleTableCommand, BorderLayout.SOUTH);
		roleTablePanel.setBorder(new TitledBorder("Goal List"));

		// create the splitter panel
		JSplitPane spliter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, roleTablePanel, null);
		spliter.setResizeWeight(0.5);

		add(spliter, BorderLayout.CENTER);
	}
	
	private void setColumnInfo(final JTable table, int columnIndex, int preferredWidth, int minWidth, int maxWidth, TableCellEditor editor) {
		TableColumn column = table.getColumnModel().getColumn(columnIndex);
		if (editor != null)
			column.setCellEditor(editor);
		column.setMaxWidth(maxWidth);
		column.setMinWidth(minWidth);
		column.setPreferredWidth(preferredWidth);
	}
	
	@Override
	public void setContext(IAppContext context) {
		super.setContext(context);
		model = context.getService(PddlModel.class);
		goalModel.setModel(model);
	}
}

class GoalTableModel extends AbstractTableModel {

	public static final int COL_NAME = 0;
	public static final int COL_TEXT = 1;
	public static final int COL_MAX_SATISFACTION = 2;
	public static final int COL_CRITICALITY = 3;
	
	private static String[] columnNames = new String[] { "Name", "Text", "Satisfaction", "Criticality" };
	
	private static final long serialVersionUID = 1L;
	private PddlModel model;

	@Override
	public int getColumnCount() {
		return columnNames.length;
	}
	
	@Override
	public String getColumnName(int column) {
		return columnNames[column];
	}

	public void setModel(PddlModel model) {
		this.model = model;
	}

	public void deleteRoles(int minSelectionIndex, int maxSelectionIndex) {
		ArrayList<PddlModel.Goal> lst = new ArrayList<PddlModel.Goal>();
		for (int i = minSelectionIndex; i <= maxSelectionIndex; i++)
			lst.add(model.Goals.get(i));
		for (PddlModel.Goal act : lst)
			model.Goals.remove(act);
		fireTableRowsDeleted(minSelectionIndex, maxSelectionIndex);
	}

	public void createNewGoal() {
		model.addGoal();
		fireTableRowsInserted(getRowCount() - 2, getRowCount() - 1);
	}

	@Override
	public int getRowCount() {
		return model.Goals.size();
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return true;
	}

	@Override
	public Object getValueAt(int rowIndex, int columnIndex) {
		PddlModel.Goal goal = model.Goals.get(rowIndex);
		switch (columnIndex) {
		case COL_NAME:
			return goal.getName();
		case COL_TEXT:
			return goal.getText();
		case COL_MAX_SATISFACTION:
			return goal.getMaxSat();
		case COL_CRITICALITY:
			return goal.getCriticality();
		}
		return null;
	}

	@Override
	public void setValueAt(Object value, int rowIndex, int columnIndex) {
		if (rowIndex >= getRowCount() || rowIndex < 0)
			return;
		PddlModel.Goal goal = model.Goals.get(rowIndex);
		switch (columnIndex) {
		case COL_NAME:
			goal.setName((String) value);
			break;
		case COL_TEXT:
			goal.setText((String) value);
			break;
		case COL_MAX_SATISFACTION:
			goal.setMaxSat((Integer) value);
			break;
		case COL_CRITICALITY:
			goal.setCriticality((Integer) value);
			break;
		}
		fireTableCellUpdated(rowIndex, columnIndex);
	}
}